<template>
  <div class="particleConversionBox"></div>
  <div id="menu">
    <button id="earth">地球</button>
    <button id="whale">海豚</button>
    <button id="star">星星</button>
    <button id="loudou">漏斗</button>
  </div>
</template>

<script>
import CONTANT from "@/lib/contant.js";
import * as THREE from "@/static/three.module.js";
import { TWEEN } from "@/static/libs/tween.module.min.js";
import { PLYLoader } from "@/static/loaders/PLYLoader.js";

export default {
  mounted() {
    //一些初始化
    var nowModel = "init";
    var scene = new THREE.Scene();
    scene.fog = new THREE.FogExp2(0x05050c, 0.0005);

    var camera = new THREE.PerspectiveCamera(
      45,
      (window.innerWidth - CONTANT.LEFT_WIDTH) /
        (window.innerHeight - CONTANT.TOP_HEIGHT),
      0.1,
      1000
    );
    camera.position.z = 350;
    camera.lookAt(new THREE.Vector3(0, 0, 0));

    var webGLRenderer = new THREE.WebGLRenderer();
    //webGLRenderer.setClearColor(new THREE.Color(0x000, 0.0));
    webGLRenderer.setClearColor(scene.fog.color);
    webGLRenderer.setSize(
      window.innerWidth - CONTANT.LEFT_WIDTH,
      window.innerHeight - CONTANT.TOP_HEIGHT
    );
    webGLRenderer.shadowMap.enabled = true;

    //光源
    var spotLight = new THREE.SpotLight(0xffffff);
    spotLight.position.set(20, 20, 20);
    scene.add(spotLight);

    document
      .querySelector(".particleConversionBox")
      .appendChild(webGLRenderer.domElement);

    //获取纹理
    var material = new THREE.PointsMaterial({
      color: 0xffffff,
      size: 5,
      opacity: 1,
      transparent: true,
      blending: THREE.AdditiveBlending,
      map: generateSprite(),
    });

    var arrTrans = [];
    setTimeout(() => {
      nowModel = "earth";
      switchType(arrEarth);
    }, 2000);

    //随机生成一些点
    var arrInit;
    var pointInit = new THREE.Object3D();
    (function () {
      var randomPoints = [];
      var geometry = new THREE.BufferGeometry();
      for (var i = 0; i < 32200; i++) {
        randomPoints.push((Math.random() - 0.5) * 1000);
      }
      var vertices = new Float32Array(randomPoints);
      geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
      pointInit = new THREE.Points(geometry, material);
      arrInit = pointInit.geometry.attributes.position.array;
      arrTrans = arrInit;
      pointInit.sortParticles = true;
      scene.add(pointInit);
      switchType();
    })();

    //加载所有模型
    var arrEarth;
    var arrWhale;
    var arrStar;
    var arrLoudou;
    (function () {
      //加载第一个模型
      new PLYLoader().load(
        CONTANT.URLPATH + "/models/_ply/earth.ply",
        function (geometry) {
          var pointEarth = new THREE.Points(geometry, material);
          arrEarth = pointEarth.geometry.attributes.position.array;
          pointEarth.sortParticles = true;
          //32199
        }
      );

      //加载第二个模型
      new PLYLoader().load(
        CONTANT.URLPATH + "/models/_ply/whale.ply",
        function (geometry) {
          var pointWhale = new THREE.Points(geometry, material);
          arrWhale = pointWhale.geometry.attributes.position.array;
          pointWhale.sortParticles = true;
          //2904
        }
      );

      //加载第三个模型
      new PLYLoader().load(
        CONTANT.URLPATH + "/models/_ply/star.ply",
        function (geometry) {
          var pointStar = new THREE.Points(geometry, material);
          arrStar = pointStar.geometry.attributes.position.array;
          pointStar.sortParticles = true;
          //13248
        }
      );

      //加载第四个模型
      new PLYLoader().load(
        CONTANT.URLPATH + "/models/_ply/loudou.ply",
        function (geometry) {
          var pointLoudou = new THREE.Points(geometry, material);
          arrLoudou = pointLoudou.geometry.attributes.position.array;
          pointLoudou.sortParticles = true;
          //4692
        }
      );
    })();

    function switchType(arrTransTo) {
      var i = 0;
      if (nowModel == "init") {
        for (i = 0; i < arrTrans.length; i++) {
          new TWEEN.Tween({ pos: 0, index: i })
            .to({ pos: 1, index: i }, 3000)
            .easing(TWEEN.Easing.Exponential.InOut)
            .onUpdate(function () {
              pointInit.rotation.y = Math.PI * 2 * this._object.pos;
            })
            .delay(Math.random() * 1000)
            .start();
        }
      } else {
        for (i = 0; i < arrTrans.length; i++) {
          var b = Math.floor(i / arrTransTo.length);
          var num = i;
          if (b * arrTransTo.length <= i) {
            num = i - b * arrTransTo.length;
          }
          new TWEEN.Tween({ pos: arrTrans[i], index: i })
            .to({ pos: arrTransTo[num], index: i }, 3000)
            .easing(TWEEN.Easing.Exponential.InOut)
            .onUpdate(function () {
              arrTrans[this._object.index] = this._object.pos;
            })
            .delay(Math.random() * 1000)
            .start();
        }
      }
    }

    //获取纹理
    function generateSprite() {
      var canvas = document.createElement("canvas");
      canvas.width = 16;
      canvas.height = 16;

      var context = canvas.getContext("2d");
      var gradient = context.createRadialGradient(
        canvas.width / 2,
        canvas.height / 2,
        0,
        canvas.width / 2,
        canvas.height / 2,
        canvas.width / 2
      );
      gradient.addColorStop(0, "rgba(255,255,255,1)");
      gradient.addColorStop(0.2, "rgba(0,255,255,1)");
      gradient.addColorStop(0.4, "rgba(0,0,64,1)");
      gradient.addColorStop(1, "rgba(0,0,0,1)");

      context.fillStyle = gradient;
      context.fillRect(0, 0, canvas.width, canvas.height);

      var texture = new THREE.Texture(canvas);
      texture.needsUpdate = true;
      return texture;
    }

    //渲染
    function render() {
      TWEEN.update();
      requestAnimationFrame(render);

      if (nowModel != "init") {
        pointInit.geometry.setAttribute(
          "position",
          new THREE.Float32BufferAttribute(arrTrans, 3)
        );
        arrTrans.sortParticles = true;
      }

      webGLRenderer.render(scene, camera);
    }
    render();

    document.getElementById("earth").addEventListener("click", function () {
      switchType(arrEarth);
    });

    document.getElementById("whale").addEventListener("click", function () {
      switchType(arrWhale);
    });

    document.getElementById("star").addEventListener("click", function () {
      switchType(arrStar);
    });

    document.getElementById("loudou").addEventListener("click", function () {
      switchType(arrLoudou);
    });
  },
};
</script>

<style>
.particleConversionBox {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

#menu {
  position: absolute;
  bottom: 20px;
  width: 100%;
  text-align: center;
}

button {
  color: rgba(127, 255, 255, 0.75);
  background: transparent;
  outline: 1px solid rgba(127, 255, 255, 0.75);
  border: 0px;
  padding: 5px 10px;
  cursor: pointer;
}

button:hover {
  background-color: rgba(0, 255, 255, 0.5);
}

button:active {
  color: #000000;
  background-color: rgba(0, 255, 255, 0.75);
}
</style>
